package com.cms.security.action;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.cms.common.action.BaseController;
import com.cms.framework.web.JsonResultMap;
import com.cms.framework.web.JsonStateEnum;
import com.cms.framework.web.WebConstants;
import com.cms.security.LoginInfo;
import com.cms.security.contants.LoginConstant;
import com.cms.setting.account.pojo.LoginAccount;
import com.cms.setting.account.service.LoginAccountService;

@RestController
public class LoginController extends BaseController{
	@Autowired
	LoginAccountService loginAccountService;
	@RequestMapping(value="/login")
	public  JsonResultMap login(HttpServletRequest request, @RequestParam("loginEmail") String loginEmail, @RequestParam("password") String password, @RequestParam(value = "inputRand", defaultValue = "") String inputRand)  {
		JsonResultMap jsonMap=new JsonResultMap(); 
		HttpSession session = request.getSession();
        LoginInfo loginInfo = new LoginInfo();
        LoginAccount loginAccount = null;
        Subject currentUser = SecurityUtils.getSubject();
        try {
            if (!currentUser.isAuthenticated()) {
            	loginAccount = loginAccountService.findByEmail(loginEmail);
                if (loginAccount == null) {
                	jsonMap.setState(JsonStateEnum.FAIL.value);
                    jsonMap.setMsg(LoginConstant.INCORRECT_USERNAME_OR_PWD);
                    return jsonMap;
                }
                UsernamePasswordToken token = new UsernamePasswordToken(loginAccount.getEmail(), password.toCharArray());
                currentUser.login(token);

                Integer loginId=loginAccount.getLoginId();
                loginInfo.setUserId(loginId);
                loginInfo.setUserName(loginAccount.getUserName());
                loginInfo.setLoginEmail(loginAccount.getEmail());
                loginInfo.setLoginAccount(loginAccount);

                currentUser.getSession().setAttribute(LoginConstant.USER, loginInfo);
                SecurityUtils.getSubject().getSession().setTimeout(-1000l);
            }
            jsonMap.setState(JsonStateEnum.SUCCESS.value); 
            jsonMap.setMsg(WebConstants.SUCCESS);
        } catch (UnknownAccountException ex) {
            // 用户名没有找到
            logger.debug("账号没有找到：" + ex);
            setIncorrectLoginTimes(session);
            //不进行明确提示，防止恶意登录
            jsonMap.setState(JsonStateEnum.FAIL.value); 
            jsonMap.setMsg(LoginConstant.INCORRECT_USERNAME_OR_PWD);
        } catch (IncorrectCredentialsException ex) {
            // 用户名密码不匹配
            logger.debug("用户名密码不匹配：" + ex);
            setIncorrectLoginTimes(session);
            jsonMap.setState(JsonStateEnum.FAIL.value); 
            jsonMap.setMsg(LoginConstant.INCORRECT_USERNAME_OR_PWD);
        } catch (AuthenticationException e) {
            logger.debug("认证异常：" + e);
            e.printStackTrace();
            setIncorrectLoginTimes(session);
            jsonMap.setState(JsonStateEnum.FAIL.value); 
            jsonMap.setMsg(LoginConstant.AUTH_EXCEPTION);
        } catch (Exception e) {
        	logger.debug("登录异常：" + e);
            e.printStackTrace();
            setIncorrectLoginTimes(session);
            jsonMap.setState(JsonStateEnum.FAIL.value); 
            jsonMap.setMsg(LoginConstant.LOGIN_EXCEPTION);
            
        } 
        // 验证码失效
        clearValidateCodeFromSession(session);
        //设置错误次数到前端
        Map<String,Object> jsonData=new HashMap<String,Object>();
        jsonData.put(WebConstants.TIMES, getIncorrectLoginTimes(session));
        jsonMap.setData(jsonData);
    	return jsonMap;
	}

	@RequestMapping("/logout")
	public  JsonResultMap loginout(HttpServletRequest request,HttpServletResponse response)  {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.getSession() != null) {
            currentUser.logout();
        }
        if (request.getSession() != null) {
            request.getSession().invalidate();
        }
        return new JsonResultMap(JsonStateEnum.SUCCESS.value,JsonStateEnum.SUCCESS.label);
	}
    @RequestMapping(value = "/chklogin", method = RequestMethod.POST)
    @ResponseBody
    public JsonResultMap chkLogin() {  
    	JsonResultMap result=new JsonResultMap();
        Subject currentUser = SecurityUtils.getSubject();  
        if (!currentUser.isAuthenticated()) {  
        	result.setState(JsonStateEnum.SUCCESS.value);
        	result.setMsg(JsonStateEnum.SUCCESS.label);
        }else{
        	result.setState(JsonStateEnum.FAIL.value);
        	result.setMsg(JsonStateEnum.FAIL.label);
        }
        return result;
    }
    
    /** 
    * 存放在session中的客户端密码登录失败次数
    * @date 2018年11月9日 上午1:10:14 
    * @param session 
    * void    返回类型 
    * @throws 
    */
    public void setIncorrectLoginTimes(HttpSession session) {
        Object o = session.getAttribute(WebConstants.INCORRECT_LOGIN_TIMES);
        String times = String.valueOf(o == null ? "0" : o);
        session.setAttribute(WebConstants.INCORRECT_LOGIN_TIMES, (Integer.parseInt(times) + 1));
    }

    /** 
    * 验证码失效
    * @date 2018年11月9日 上午1:10:28 
    * @param session 
    * void    返回类型 
    * @throws 
    */
    public void clearValidateCodeFromSession(HttpSession session) {
        session.removeAttribute(WebConstants.LOGIN_IMAGE_RAND_CODE);
    }
    /** 
    * 获取登录时的错误次数
    * @date 2018年11月9日 上午1:10:43 
    * @param session
    * @return 
    * int    返回类型 
    * @throws 
    */
    public int getIncorrectLoginTimes(HttpSession session) {
        Object o = session.getAttribute(WebConstants.INCORRECT_LOGIN_TIMES);
        return Integer.parseInt(String.valueOf(o == null ? 0 : o));
    }     
}
